<?php

namespace App\Supports\Payment\Methods\Alibatch;

use Carbon\Carbon;
use App\Models\Withdraw;
use App\Models\BatchWithdraw;
use App\Supports\Payment\Methods\Method;
use App\Supports\Payment\Contracts\MethodCallback;

class CallbackWithdraw extends Method implements MethodCallback
{
	public function getBatchWithdraw(array $data)
	{
		return BatchWithdraw::query()
			->where('batch_number', $data['out_batch_no'])
			->where('ali_batch_id', $data['batch_trans_id'])
			->first();
	}
	
	public function markAsPaid($batch = null, $data = null)
	{
		$query = cashier('alibatch')->queryWithdrawBatch($batch);
		$queryResult = collect($query->acc_detail_list);
		
		if ($queryResult->isEmpty()) return 'fail';
		
		$batch->update([
			'ali_batch_id' => $data['batch_trans_id'],
			'success_count' => $data['success_count'],
			'success_amount' => $data['success_amount'],
			'failed_count' => $data['fail_count'],
			'failed_amount' => $data['fail_amount'],
			'status' => 'success',
			'remark' => 'SUCCESS 批次处理成功(全部或者部分成功)'
		]);
		
		$withdraws = $batch->withdraws()->get();
		
		foreach ($withdraws as $withdraw) {
			
			$detail = $queryResult
				->where('out_biz_no', 'withdraw_'.$withdraw->number)->first();
			
			if (! $detail) continue;
			
			if ($detail->status == 'SUCCESS') {
				$withdraw->update([
					'paid_at' => Carbon::now(),
					'paid_no' => $detail->detail_id,
					'status' => 'paid',
				]);
			} else {
				$status = $detail->status;
				$remark = $detail->remark;
				$errorCode = $detail->error_code;
				$errorMsg = $detail->error_msg;
				$withdraw->update([
					'status' => 'failed',
					'remark' => "{$status}-{$remark}-{$errorCode}-{$errorMsg}"
				]);
			}
		}
		
		return 'success';
	}
	
	protected function updateBatchStatus(array $data)
	{
		$status = isset($data['batch_status']) ? $data['batch_status'] : null;
		
		if (!$status) return 'fail';
		
		$batch = $this->getBatchWithdraw($data);
		
		if (!$batch) return 'fail';
		
		if ($status == 'SUCCESS') {
			return $this->markAsPaid($batch, $data);
		} elseif ($status == 'PART_SUCCESS') {
			return $this->markAsPaid($batch, $data);
		} elseif ($status == 'FAIL') {
			$batch->update([
				'ali_batch_id' => $data['batch_trans_id'],
				'status' => 'failed',
				'remark' => 'FAIL 全部处理失败',
			]);
			return 'success';
		} elseif ($status == 'INVALID') {
			$batch->update([
				'ali_batch_id' => $data['batch_trans_id'],
				'status' => 'failed',
				'remark' => 'INVALID 批次无效(如收款方信息全部错误)',
			]);
			return 'success';
		} elseif ($status == 'DISUSE') {
			$batch->update([
				'ali_batch_id' => $data['batch_trans_id'],
				'status' => 'failed',
				'remark' => 'DISUSE 批次单据废弃',
			]);
			return 'success';
		} else {
			return 'fail';
		}
	}
	
	protected function updateDirectStatus(array $data)
	{
		if (! isset($data['out_biz_no'])) return 'fail';
		
		$number = $this->getPaidNumber($data['out_biz_no']);
		
		$withdraw = Withdraw::where('number', $number)->first();
		
		if (! $withdraw) return 'fail';
		
		if ($withdraw->paid_no) return 'success';
		
		if ($data['status'] == 'SUCCESS') {
			$withdraw->update([
				'paid_at' => Carbon::now(),
				'paid_no' => $data['order_id'],
				'status' => 'paid'
			]);
			return 'success';
		}
		return 'fail';
	}
	
	public function callback($data = null)
	{
		$result = $this->channel->verify();
		
		if (empty($result)) return 'fail';
		
		if (isset($result['biz_scene']) and $result['biz_scene'] == 'DIRECT_TRANSFER') {
			return $this->updateDirectStatus($result);
		}
		
		return $this->updateBatchStatus($result);
	}
}
